package com.zhuxulin.midi.util;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;

import com.zhuxulin.midi.MidiFile;
import com.zhuxulin.midi.MidiTrack;
import com.zhuxulin.midi.event.MidiEvent;
/**
 * Provide some mid Event Tools
 * @author ZhuXulin
 *
 */
public class PianoUtils {
	private File mid = null;
	private MidiFile midiFile = null;
	private TreeSet<MidiEvent> allEvents = null;
	// private ArrayList<MidiTrack> allTracks = null;
	private List<MidiEvent> allUsefulTicks = null;

	public PianoUtils(File mid) {
		this.mid = mid;
		init();
	}

	public PianoUtils(String mid) {
		this.mid = new File(mid);
		init();
	}

	/**
	 * initialize the piano
	 */
	private void init() {
		allEvents = new TreeSet<MidiEvent>();
		try {
			midiFile = new MidiFile(mid);
		} catch (IOException e) {
			e.printStackTrace();
		}
		// allTracks = midiFile.getTracks();
		for (MidiTrack t : midiFile.getTracks()) {
			allEvents.addAll(t.getEvents());
		}
		allUsefulTicks = getAllTicksList();
	}

	/**
	 * Get the events that has the given tick!
	 * 
	 * @param nowTick
	 * @return
	 */
	public List<MidiEvent> getEventsWithTick(long nowTick) {
		Iterator<MidiEvent> it = allEvents.iterator();
		List<MidiEvent> events = new ArrayList<MidiEvent>();
		boolean over = false;
		while (it.hasNext()) {
			MidiEvent e = it.next();
			if (e.getTick() == nowTick) {
				events.add(e);
				over = true;
				continue;
			}
			if (over) {
				break;
			}
		}
		return events;
	}

	/**
	 * Get the next tick with the given tick!
	 * 
	 * @param allUsefulTicks
	 * @param nowTick
	 * @return
	 */
	public long getNextTick(long nowTick) {
		Iterator<MidiEvent> it = allUsefulTicks.iterator();
		MidiEvent e = null;
		while (it.hasNext()) {
			e = it.next();
			if (e.getTick() > nowTick) {
				return e.getTick();
			}
		}
		return -1;
	}

	/**
	 * Get all useful tick!
	 * 
	 * @return
	 */
	private List<MidiEvent> getAllTicksList() {
		List<MidiEvent> ticks = null;
		Iterator<MidiEvent> it = allEvents.iterator();
		MidiEvent next = null;
		MidiEvent now = it.hasNext() ? it.next() : null;
		if (now == null) {
			return null;
		}
		ticks = new ArrayList<MidiEvent>();
		ticks.add(now);
		while (it.hasNext()) {
			next = it.next();
			if (now.getTick() != next.getTick()) {
				ticks.add(next);
				now = next;
			}
		}
		return ticks;
	}

	public long getLengthInTicks() {
		return midiFile.getLengthInTicks();
	}

	public int getResolution() {
		return midiFile.getResolution();
	}

	public int getTrackCount() {
		return midiFile.getTrackCount();
	}

	public int getType() {
		return midiFile.getType();
	}
}
